package wallpaperCtrl.screenCtrl;

import wallpaperCtrl.command.CommandLinux;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ScreenCtrlLinux implements ScreenCtrl {
    private static final ScreenCtrlLinux screenCtrlLinux;

    static {
        screenCtrlLinux = new ScreenCtrlLinux();
    }

    @Override
    public List<WindowStatus> getAllWindowStatus() {
        List<WindowStatus> allWindow = getAllWindowStatic();
        for (WindowStatus windowStatus : allWindow) {
            String[] args = new String[]{"/bin/bash", "-c", "xwininfo -id " + windowStatus.getId() + " -frame"};
            try {
                String output = CommandLinux.oSCommandStatic(args);
                getWindowStatus(output, windowStatus);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return allWindow;
    }

    public static List<WindowStatus> getAllWindowStatusStatic() {
        return screenCtrlLinux.getAllWindowStatus();
    }

    @Override
    public List<WindowStatus> getAllWindow() {
        List<WindowStatus> statuses = new ArrayList<>();
        String[] args = new String[]{"/bin/bash", "-c", "wmctrl -l"};
        try {
            String output = CommandLinux.oSCommandStatic(args);
            String[] strings = output.split("\n");

            for (int i = 0; i < strings.length; i++) {
                int t = 0;
                WindowStatus windowStatus = new WindowStatus();
                String[] str = strings[i].split(" ");
                windowStatus.setId(str[t++]);
                if (str[t] .equals("") ) {
                    t++;
                }
                windowStatus.setDesk(str[t++]);
                t++;
                for (int j = str.length - 1; j > t; j--) {
                    str[j - 1] += " " + str[j];
                }
                windowStatus.setName(str[t]);
                statuses.add(windowStatus);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return statuses;
    }

    public static List<WindowStatus> getAllWindowStatic() {
        return screenCtrlLinux.getAllWindow();
    }

    @Override
    public WindowStatus getSelectWindowStatus() {
        String[] args = new String[]{"/bin/bash", "-c", "xwininfo"};
        String regEx = null;
        try {
            String oSCommandStr = CommandLinux.oSCommandStatic(args);
            WindowStatus windowStatus = new WindowStatus();
            regEx = getRegEx("Window id: [a-zA-Z0-9]+", oSCommandStr);
            regEx = regEx.replace("Window id: ", "");
            windowStatus.setId(regEx);
            args = new String[]{"/bin/bash", "-c", "xwininfo -id " + regEx + " -frame"};
            oSCommandStr = CommandLinux.oSCommandStatic(args);
            getWindowStatus(oSCommandStr, windowStatus);
            regEx = getRegEx("\"(.*)\"", oSCommandStr);
            regEx = regEx.replaceAll("\"", "");
            windowStatus.setName(regEx);
            args = new String[]{"/bin/bash", "-c", "wmctrl -l"};
            String output = CommandLinux.oSCommandStatic(args);
            String[] strings = output.split("\n");
            for (int i = 0; i < strings.length; i++) {
                int t = 0;
                String[] str = strings[i].split(" ");
                t++;
                if (str[t].equals("")) {
                    t++;
                }
                String desk = str[t++];
                t++;
                for (int j = str.length - 1; j > t; j--) {
                    str[j - 1] += " " + str[j];
                }
                if (str[t].equals(regEx)){
                    windowStatus.setDesk(desk);
                }
            }
            return windowStatus;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static WindowStatus getSelectWindowStatusStatic() {
        return screenCtrlLinux.getSelectWindowStatus();
    }

    @Override
    public void moveWindowTo(String id, int g, int x, int y, int width, int height) {
        String[] args = new String[]{"/bin/bash", "-c", "wmctrl -i -r " + id + " -e " + g + "," + x + "," + y + "," + width + "," + height};
        String s = null;
        try {
            s = CommandLinux.oSCommandStatic(args);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(s);
        }
    }

    @Override
    public WindowStatus getDeskWindowStatus() {
        String[] args = new String[]{"/bin/bash", "-c", "wmctrl -l"};
        try {
            String oSCommandStatic = CommandLinux.oSCommandStatic(args);
            String[] strings = oSCommandStatic.split("\n");
            int t = 0;
            WindowStatus windowStatus = new WindowStatus();
            String[] str = strings[0].split(" ");
            windowStatus.setId(str[t++]);
            if (str[t].equals("")) {
                t++;
            }
            windowStatus.setDesk(str[t++]);
            t++;
            for (int j = str.length - 1; j > t; j--) {
                str[j - 1] += " " + str[j];
            }
            windowStatus.setName(str[t]);
            args = new String[]{"/bin/bash", "-c", "xwininfo -id " + windowStatus.getId() + " -frame"};
            try {
                String output = CommandLinux.oSCommandStatic(args);
                getWindowStatus(output, windowStatus);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return windowStatus;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static WindowStatus getDeskWindowStatusStatic() {
        return screenCtrlLinux.getDeskWindowStatus();
    }

    @Override
    public MouseLocation getMouseLocation() {
        String[] args = new String[]{"/bin/bash", "-c", "xdotool getmouselocation"};
        MouseLocation mouseLocation = new MouseLocation();
        try {
            String s = CommandLinux.oSCommandStatic(args);
            System.out.println(s);
            mouseLocation.setX(Integer.parseInt(getRegEx("x:[0-9]+", s).replace("x:", "")));
            mouseLocation.setY(Integer.parseInt(getRegEx("y:[0-9]+", s).replace("y:", "")));
            return mouseLocation;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static MouseLocation getMouseLocationStatic() {
        return screenCtrlLinux.getMouseLocation();
    }

    public static void moveWindowToStatic(String id, int g, int x, int y, int width, int height) {
        screenCtrlLinux.moveWindowTo(id, g, x, y, width, height);
    }

    @Override
    public void moveWindowTo(String id, int x, int y, int width, int height) {
        moveWindowTo(id, 0, x, y, width, height);
    }

    public static void moveWindowToStatic(String id, int x, int y, int width, int height) {
        new ScreenCtrlLinux().moveWindowTo(id, x, y, width, height);
    }

    private static void getWindowStatus(String input, WindowStatus windowStatus) {
        String regEx = null;
        regEx = getRegEx("Absolute upper-left X:  [-+]?[0-9]+", input);
        regEx = regEx.replace("Absolute upper-left X:  ", "");
        windowStatus.setX(regEx);
        regEx = getRegEx("Absolute upper-left Y:  [-+]?[0-9]+", input);
        regEx = regEx.replace("Absolute upper-left Y:  ", "");
        windowStatus.setY(regEx);
        regEx = getRegEx("Width: [-+]?[0-9]+", input);
        regEx = regEx.replace("Width: ", "");
        windowStatus.setWidth(regEx);
        regEx = getRegEx("Height: [-+]?[0-9]+", input);
        regEx = regEx.replace("Height: ", "");
        windowStatus.setHeight(regEx);
    }

    private static String getRegEx(String patternstr, String str) {//
        str = "###" + str;
        Pattern pattern = Pattern.compile(patternstr);
        Matcher matcher = pattern.matcher(str);
        boolean matches = matcher.matches();
        String ans = null;
        while (matcher.find()) {
            ans = matcher.group();
        }
        return ans;
    }


}
